package capitulo7;

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.net.URL;

import javax.swing.JFrame;

// AnimatedSprite class
public class AnimatedSprite {
	protected JFrame frame;
	protected Graphics2D g2d;
	public Image image;
	public boolean alive;
	public Point position;
	public Point velocity;
	public double rotationRate;
	public int currentState;
	public int currentFrame, totalFrames;
	public int animationDirection;
	public int frameCount, frameDelay;
	public int frameWidth, frameHeight, columns;
	public double moveAngle, faceAngle;
	
	// Constructor
	public AnimatedSprite(JFrame _frame, Graphics2D _g2d){
		frame = _frame;
		g2d = _g2d;
		image = null;
		alive = false;
		position = new Point(0,0);
		velocity = new Point(0,0);
		rotationRate = 0.0;
		currentState = 0;
		currentFrame = 0;
		totalFrames = 1;
		animationDirection = 1;
		frameCount = 0;
		frameDelay = 0;
		frameWidth = 0;
		frameHeight = 0;
		columns = 1;
		moveAngle = 0.0;
		faceAngle = 0.0;
	}

	// Setters & getters of protected variables
	public JFrame getJFrame() { return frame; }
	public Graphics2D getGraphics() { return g2d; }
	public void setGraphics(Graphics2D _g2d) { g2d = _g2d; }
	
	// Methods for the image (Overload)
	public void setImage(Image _image) { image = _image; }
	
	public void load(String filename, int _columns, int _totalFrames, int _width, int _height){
		Toolkit tk = Toolkit.getDefaultToolkit();
		image = tk.getImage(getURL(filename));
		while(image.getWidth(frame)<=0);			// Waits for the full load of the image
		columns = _columns;
		totalFrames = _totalFrames;
		frameWidth = _width;
		frameHeight = _height;
	}
	
	protected URL getURL(String filename){
		URL url = null;
		try  {
			url = this.getClass().getResource(filename);
		} catch (Exception e) { e.printStackTrace(); }
		
		return url;
	}
	
	// Methods to know the width and Height
	public int getWidth(){
		if (image!=null) 
			return image.getHeight(frame);
		else
			return 0;
	}
	
	public int getHeight(){
		if (image!=null)
			return image.getHeight(frame);
		else
			return 0;
	}
	
	// Methods to get the center of the image
	public int getCenterX(){
		return position.x + getWidth()/2;
	}
	
	public int getCenterY(){
		return position.y + getHeight()/2;
	}
	
	public Point getCenter(){
		return (new Point((int)getCenterX(),(int)getCenterY()));
	}
	
	// Rectangle for collision
	public Rectangle getBounds(){
		return (new Rectangle((int)position.x, (int)position.y, frameWidth, frameHeight));
	}
	
	// Update Method
	protected void update(){
		// Update Position
		position.x += velocity.x;
		position.y += velocity.y;
		
		// UpdateRotation
		if (rotationRate > 0.0) {
			faceAngle += rotationRate;
			if (faceAngle < 0)
				faceAngle = 360 - rotationRate;
			else if (faceAngle > 360) 
				faceAngle = rotationRate;
		}
		
		// Update Animation
		if (totalFrames > 1){
			frameCount++;
			if (frameCount > frameDelay){
				frameCount = 0;
				currentFrame += animationDirection;
				if (currentFrame > totalFrames+1) {
					currentFrame = 0;
				} else if (currentFrame < 0){
					currentFrame = totalFrames-1;
				}
			}
		}
	}
	
	public void drawBounds(Color c){
		g2d.setColor(c);
		g2d.draw(getBounds());
	}
	
	public void draw() {
		update();
		
		//get the current frame
		int frameX = (currentFrame%columns)*frameWidth;
		int frameY = (currentFrame/columns)*frameHeight;
		
		// draw Image
		g2d.drawImage(image, position.x, position.y, position.x+frameWidth,position.y+frameHeight,frameX, frameY,frameX+frameWidth, frameY+frameHeight, getJFrame()); 
	}
	
	// Check for Collision with a rectangular shape
	public boolean collidesWidth(Rectangle rect){
		return (rect.intersects(getBounds()));
	}
	
	// Check for collision with another sprite
	public boolean collidesWidth(AnimatedSprite sprite){
		return(getBounds().intersects(sprite.getBounds()));
	}
	
	// Check for collision with a point
	public boolean collidesWidth(Point point){
		return (getBounds().contains(point));
	}
}